#![allow(non_snake_case)]

use chrono::{Datelike, NaiveDate};
use leptos::{html, prelude::*};
use leptos_icons::*;
use icondata as i;
use shq_common::prelude::Size;
use super::panel::{Panel, PanelRef};
use thaw_components::{Follower, FollowerPlacement};
use thaw_utils::{now_date, ArcOneCallback, BoxOneCallback, ComponentRef, Model, SignalWatch};
use crate::_binder::Binder;
use crate::{date_picker::panel::PanelVariant, input::{Input, InputSuffix}, InputPrefix};

#[component]
pub fn MonthPicker(
    #[prop(optional, into)] value: Model<Option<i32>>,
    #[prop(optional, into)] placeholder: MaybeProp<String>,
    #[prop(optional, into)] on_change: Option<BoxOneCallback<Option<i32>>>,
    #[prop(optional, into)] size: MaybeProp<Size>,
    #[prop(optional)] input_prefix: Option<InputPrefix>,
    #[prop(optional)] input_suffix: Option<InputSuffix>,
    #[prop(optional, into)] disabled: MaybeProp<bool>,
    #[prop(default=true.into(), into)] border: MaybeProp<bool>,
    #[prop(optional)] inner_max_width: u32,
    #[prop(optional)] is_init_focus: bool,
) -> impl IntoView {
    let date_picker_ref = NodeRef::<html::Div>::new();
    let is_show_panel = RwSignal::new(false);
    let show_date_text: RwSignal<Option<String>> = RwSignal::new(None);
    let update_show_date_text = move || {
        value.with_untracked(move |year_month| {
            let text = year_month.as_ref().map_or(None, |year_month| {
                let year=year_month/100;
                let month=year_month%100;
                Some(format!("{:04}-{:02}", year, month))
            });
            show_date_text.set(text);
        });
    };
    update_show_date_text();
    let panel_ref = ComponentRef::<PanelRef>::default();
    let panel_selected_date = RwSignal::new(None::<NaiveDate>);
    let show_date_format = "%Y%m";
    _ = panel_selected_date.watch(move |date| {
        let text = date.as_ref().map_or(None, |date| {
            Some(date.format(show_date_format).to_string())
        });
        show_date_text.set(text);
    });


    let close_panel = ArcOneCallback::new(move |date: Option<NaiveDate>| {
        if date.is_none() {
            is_show_panel.set(false);
            return;
        }
        if let Some(panel_ref) = panel_ref.get_untracked() {
            let pv=panel_ref.variant.get();
            let y_m=if pv==PanelVariant::Month {
                date.map(|d|(d.year(),d.month() as i32))
            }else {
                let year=date.map(|d|d.year()).unwrap_or(NaiveDate::default().year());
                let month=value.get().map(|v|v.abs()%100).unwrap_or(1);
                Some((year,month))
            };
            let month=y_m.map(|(year,month)|year*100+month);
            if let Some(on_change)=on_change.as_ref() {
                on_change(month);
            }
            value.set(month);
            update_show_date_text();
            if pv==PanelVariant::Month {
                is_show_panel.set(false);
            } else{
                let y_m=y_m.unwrap();
                let date=NaiveDate::from_ymd_opt(y_m.0, y_m.1 as u32, 1).unwrap();
                panel_ref.init_panel(date,PanelVariant::Month);
            }
        }else{
            is_show_panel.set(false);
        }
    });

    let open_panel = BoxOneCallback::new(move |_| {
        let date=value.get_untracked().map(|year_month|{
            let y=year_month/100;
            let m=(year_month.abs()%100) as u32;
            NaiveDate::from_ymd_opt(y, m, 1).unwrap()
        });
        panel_selected_date.set(date);
        if let Some(panel_ref) = panel_ref.get_untracked() {
            panel_ref.init_panel(date.unwrap_or(now_date()),PanelVariant::Month);
        }
        is_show_panel.set(true);
    });
    view! {
        <Binder>
            <div node_ref=date_picker_ref>
                <Input value=show_date_text on_focus=open_panel border size disabled placeholder input_prefix inner_max_width is_init_focus>
                    <InputSuffix slot>
                        <Icon icon=i::AiCalendarOutlined style="font-size: 18px"/>
                        {if let Some(suffix) = input_suffix.and_then(|suffix| suffix.if_.then_some(suffix)) {
                            view! { {(suffix.children)()} }.into()
                        } else {
                            None
                        }}
                    </InputSuffix>
                </Input>
            </div>
            <Follower slot show=is_show_panel placement=FollowerPlacement::BottomStart>
                <Panel
                    date_picker_ref
                    close_panel
                    selected_date=panel_selected_date
                    comp_ref=panel_ref
                    is_show_panel
                    selected_variant=PanelVariant::Month.into()
                />
            </Follower>
        </Binder>
    }
}
